/*
 * Copyright (C) 2012-2020 Markus Junginger, greenrobot (http://greenrobot.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.greenrobot.eventbus;

import android.os.Looper;

import org.greenrobot.eventbus.android.AndroidLogger;
import org.greenrobot.eventbus.meta.SubscriberInfoIndex;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Creates EventBus instances with custom parameters and also allows to install a custom default EventBus instance.
 * Create a new builder using {@link EventBus#builder()}.
 * 使用自定义参数创建EventBus实例，还允许安装自定义默认EventBus实例。
 * 使用{@link EventBus＃builder（）}创建一个新的生成器。
 */
@SuppressWarnings("unused")
public class EventBusBuilder {

    /**
     * 创建线程池
     */
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;
    List<SubscriberInfoIndex> subscriberInfoIndexes;
    Logger logger;
    MainThreadSupport mainThreadSupport;

    EventBusBuilder() {
    }

    /**
     * Default: true
     */
    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }

    /**
     * Default: true
     */
    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }

    /**
     * Default: true
     */
    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }

    /**
     * Default: true
     */
    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }

    /**
     * Fails if an subscriber throws an exception (default: false).
     * 如果订户引发异常，则失败（默认值：false）。
     * <p/>
     * Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss
     * 提示：将它与BuildConfig.DEBUG一起使用可使应用程序在DEBUG模式下崩溃（仅）。这样，您就不会错过
     * exceptions during development.
     * 开发过程中的异常
     */
    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
        this.throwSubscriberException = throwSubscriberException;
        return this;
    }

    /**
     * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).
     * 默认情况下，EventBus考虑事件类层次结构（将通知超类的订阅者）。
     * Switching this feature off will improve posting of events. For simple event classes extending Object directly,
     * 关闭此功能将改善事件的发布。对于直接扩展Object的简单事件类，
     * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be
     * 我们将事件发布的速度提高了20％。对于更复杂的事件层次结构，速度应为
     * greater than 20%.
     * 大于20％。
     * <p/>
     * However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,
     * 但是，请记住，事件发布通常只占用应用程序内部CPU时间的一小部分，
     * unless it is posting at high rates, e.g. hundreds/thousands of events per second.
     * 除非它以高速率发布，例如每秒成百上千个事件。
     */
    public EventBusBuilder eventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
        return this;
    }


    /**
     * Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced
     * 为用于异步和后台事件传递的EventBus提供一个自定义线程池。这是高级
     * setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.
     * 设置可能会破坏事情：确保给定的ExecutorService不会卡住，以避免未定义的行为。
     */
    public EventBusBuilder executorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    /**
     * Method name verification is done for methods starting with onEvent to avoid typos; using this method you can
     * 方法名称验证是对以onEvent开头的方法进行的，以避免输入错误；使用这种方法，您可以
     * exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor
     * 从此检查中排除订户类别。还禁用对方法修饰符的检查（公共，非静态或
     * abstract).
     * 抽象的）。
     */
    public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
        if (skipMethodVerificationForClasses == null) {
            skipMethodVerificationForClasses = new ArrayList<>();
        }
        skipMethodVerificationForClasses.add(clazz);
        return this;
    }

    /**
     * Forces the use of reflection even if there's a generated index (default: false).
     * 即使存在生成的索引，也强制使用反射（默认值：false）。
     */
    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
        return this;
    }

    /**
     * Enables strict method verification (default: false).
     * 启用严格的方法验证（默认值：false）。
     */
    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
        this.strictMethodVerification = strictMethodVerification;
        return this;
    }

    /**
     * Adds an index generated by EventBus' annotation preprocessor.
     * 添加由EventBus的注释预处理器生成的索引。
     */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if (subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

    /**
     * Set a specific log handler for all EventBus logging.
     * 为所有EventBus日志设置特定的日志处理程序。
     * <p/>
     * By default all logging is via {@link android.util.Log} but if you want to use EventBus
     * 默认情况下，所有日志记录都是通过{@link android.util.Log}进行的，但是如果您想使用EventBus
     * outside the Android environment then you will need to provide another log target.
     * 在Android环境之外，则需要提供另一个日志目标。
     */
    public EventBusBuilder logger(Logger logger) {
        this.logger = logger;
        return this;
    }

    Logger getLogger() {
        if (logger != null) {
            return logger;
        } else {
            return Logger.Default.get();
        }
    }

    MainThreadSupport getMainThreadSupport() {
        if (mainThreadSupport != null) {
            return mainThreadSupport;
        } else if (AndroidLogger.isAndroidLogAvailable()) {
            Object looperOrNull = getAndroidMainLooperOrNull();
            return looperOrNull == null ? null :
                    new MainThreadSupport.AndroidHandlerMainThreadSupport((Looper) looperOrNull);
        } else {
            return null;
        }
    }

    static Object getAndroidMainLooperOrNull() {
        try {
            return Looper.getMainLooper();
        } catch (RuntimeException e) {
            // Not really a functional Android (e.g. "Stub!" maven dependencies)
            return null;
        }
    }

    /**
     * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
     * 使用此构建器的值安装{@link EventBus＃getDefault（）}返回的默认EventBus。必须是
     * done only once before the first usage of the default EventBus.
     * 在第一次使用默认EventBus之前仅执行一次。
     *
     * @throws EventBusException if there's already a default EventBus instance in place
     *                           如果已经有一个默认的EventBus实例
     */
    public EventBus installDefaultEventBus() {
        synchronized (EventBus.class) {
            if (EventBus.defaultInstance != null) {
                throw new EventBusException("Default instance already exists." +
                        " It may be only set once before it's used the first time to ensure consistent behavior.");
            }
            EventBus.defaultInstance = build();
            return EventBus.defaultInstance;
        }
    }

    /**
     * Builds an EventBus based on the current configuration.
     * 根据当前配置构建一个EventBus。
     */
    public EventBus build() {
        return new EventBus(this);
    }

}
